#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   conftest.py
@Time    :   2022/02/23 09:16:36
@Author  :   yangliang 
@Version :   1.0
@Contact :   yangl@genvict.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''
import shutil
import sys
import os
import logging

from commDriver.jidianqi import JDQSerialController
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.abspath(os.path.dirname(curPath) + os.path.sep + ".")
sys.path.append(rootPath)
sys.path.append(os.path.join(curPath,'commDriver'))
sys.path.append(os.path.join(curPath,'data'))
sys.path.append(os.path.join(curPath,'commDriver/zlg'))
logging.info(sys.path)


# here put the import lib
import pytest
import sys
import os
import time
import datetime
import allure
from py._xmlgen import html
import traceback

# from commDriver.CAN import *
# from commDriver.TS_CAN import *
# from commDriver.power import *
from project_CAN_TC import *
import project_CAN_TC
from project_CAN_ZLG import *
import project_CAN_ZLG
from commDriver.zlg.zlgcan import *
from commDriver.zlg.zuds_test_main import *
from commDriver.power_2303 import *
from commDriver.power_it6720 import *
from commDriver.zlg.dbc import *
from commDriver.zlg.zlgdbc import *
from commDriver.m600_communicator import *

import Set_up

__Driver = {}

sys.dont_write_bytecode = True


# 这里我设置的级别是模块级别,也就是每个测试文件运行一次
# 可以设置为session,全部用例执行一次
@pytest.fixture(scope='session')
def Driver():
    global __Driver

    # Init CAN Tool
    try:
        logging.info("open CAN_Driver".center(50, '-'))
        if Set_up.drive_type != ZCAN_USBCANFD_200U:
            project_rbs = real_CAN_TC(Set_up.drive_type,Set_up.configure_baudrate,TSMasterAPI.CHANNEL_INDEX.CHN1)
            project_rbs.load_dbc(Set_up.project_DBC_File_CAN, ASupportedChannelsBased = '0')

            project_rbs.register_event_canfd_T_pre(OnCANPreFDevent)
            project_rbs.register_event_canfd_T_R(OnCANPreFDevent_checkPCAN)
            project_rbs.connect_application()
            project_rbs.RBS_Config(Set_up.NetName,Set_up.EnableNode)
            project_rbs.start_rbs()

            project_rbs.write_db_signal(Set_up.NetName,'VIU0', 'VIU_Route_Body3', 'IPB_VehicleSpeedValid2', 1)
            project_rbs.write_db_signal(Set_up.NetName,'VIU0', 'VIU_Route_Body3', 'IPB_VehicleSpeed2', 0)
            project_rbs.write_db_signal(Set_up.NetName,'EWS_F', 'EWS_F_St', 'EWS_F_RxLost', 1)
            project_rbs.write_db_signal(Set_up.NetName,'VIU0', 'TBOX_TimeInfo_VV03', 'TBOX_TimeFlag', 1)
            
            # project_rbs.set_0x1C2_rolling_counter_error(enable=False)
            # project_rbs.set_0x1C2_checksum_error(enable=False)

        if Set_up.drive_type == ZCAN_USBCANFD_200U:
            project_rbs = real_CAN_ZLG(Set_up.drive_type,Set_up.drive_index,Set_up.chn_index,Set_up.can_abit,Set_up.can_bbit)
            project_rbs.Open_CAN()
            project_rbs.init_uds()

            project_rbs.register_signal_receiver(0x3E6, my_receive_callback(project_rbs))
        
            # 开启车身信号发送
            # db = DBCParser(Set_up.project_DBC_File_CAN)
            # signal_configs = db.parse_signals(1)
            signal_configs  = project_rbs.parse_dbc_to_list(Set_up.project_DBC_File_CAN)
            project_rbs.start_multiple_signal_loops(signal_configs)
            

            # project_rbs.update_signal_data(0x90, index=[2], value=[0x40])
            time.sleep(0.5)
            project_rbs.update_signal_data(0x90, signal_name='PwrModSts', value=2)
            project_rbs.update_signal_data(0x106, signal_name='VehSpdVld', value=1)
            project_rbs.update_signal_data(0x107, [0x00, 0x19, 0x03, 0x21, 0x09, 0x19, 0x20, 0x25])

        __Driver['CAN'] = project_rbs
        logging.info("open CAN_Driver success".center(50, '-'))
        # __Driver['PLC'] = Modbus
        # logging.info("open CAN_Driver2 success".center(50, '-'))

        
    except Exception as e:
        logging.info(traceback.print_exc())
        __Driver['CAN'].close_can()
        logging.info("open CAN_Driver failed".center(50, '-'))
        
    if Set_up.drive_type == ZCAN_USBCANFD_200U:
        # Init UDS support
        try:
            diag = project_rbs
            diagfun = project_rbs
            __Driver['UDS'] = diag
            __Driver['UDSFun'] = diagfun
            # diag.req_and_res_can([0x22,0xf1,0x90],3)
            # diag.UDS_can_delete()
            logging.info("Creat UDS_Handle successful".center(50, '-'))
            pass
        except Exception as e:
            logging.info("Creat UDS_Handle failed ".center(50, '-'))
            pass
    else:
        # Init UDS support
        try:
            if Set_up.CAN_Type == 'CAN':
                SupportFD = 0
                Maxdlc = 8
            else:
                SupportFD = 1
                Maxdlc = 16

            diag = TSCAN_UDS(ASupportFD=SupportFD, AMaxdlc=Maxdlc, reqID=Set_up.reqID,resID=Set_up.resID,AFctID=Set_up.AFctID)
            diagfun = TSCAN_UDS(reqID=Set_up.AFctID,resID=Set_up.resID,AFctID=Set_up.AFctID)
            __Driver['UDSFun'] = diagfun
            __Driver['UDS'] = diag
            # diag.req_and_res_can([0x22,0xf1,0x90],3)
            # diag.UDS_can_delete()
            logging.info("Creat UDS_Handle successful".center(50, '-'))
            pass
        except Exception as e:
            logging.info("Creat UDS_Handle failed ".center(50, '-'))
            pass

    # __Driver['CAN'].set_FDmode(TSMasterAPI.CHANNEL_INDEX.CHN1, True, True, Maxdlc)
    # __Driver['CAN'].set_FDmode(TSMasterAPI.CHANNEL_INDEX.CHN2, True, True, Maxdlc)


    # Init Power supply
    try:
        logging.info("open power_Driver".center(50, '-'))

        if Set_up.power_Type == '2303':
            project_power = PowerSupplyController(Set_up.gpib_address)
            project_power.turn_on_power()
            project_power.set_voltage(12)
        else:
            project_power = IT6720SerialController()
            project_power.connect()
        __Driver['power'] = project_power
        time.sleep(1)
        logging.info("open power_Driver success".center(50, '-'))
    except Exception as e:
        logging.info(traceback.print_exc())
        try:
            __Driver['power'].turn_off_power()
        except Exception as e: 
            pass  
        logging.info("open power_Driver failed ".center(50, '-'))

    # Init jidianqi
    try:
        logging.info("open jidianqi".center(50, '-'))
        project_jidianqi = JDQSerialController(Set_up.jidianqiPort,Set_up.jidianqiBaudrate,Set_up.jidianqiTimeOut)
        __Driver['jidianqi'] = project_jidianqi
        time.sleep(0.5)
        logging.info("open jidianqi success".center(50, '-'))
    except Exception as e:
        logging.info(traceback.print_exc())
        try:
            __Driver['jidianqi'].close()
        except Exception as e: 
            pass  
        logging.info("open jidianqi failed ".center(50, '-'))

    # Init M600T
    try:
        logging.info("open M600T_Driver".center(50, '-'))
        project_m600t = M600Communicator(Set_up.M600Tport,Set_up.M600Tbaudrate,Set_up.M600TTimeOut)
        __Driver['M600'] = project_m600t
        time.sleep(0.5)
        logging.info("open M600T_Driver success".center(50, '-'))
    except Exception as e:
        logging.info(traceback.print_exc())
        try:
            __Driver['M600'].close()
        except Exception as e: 
            pass  
        logging.info("open M600T_Driver failed ".center(50, '-'))

    yield __Driver
    if Set_up.drive_type == ZCAN_USBCANFD_200U:
        __Driver['CAN'].stop_multiple_signal_loops()
        __Driver['CAN'].close_can()
        logging.info("close CAN_Driver".center(50, '-'))
    else:
        __Driver['CAN'].dis_connect_application()
        logging.info("close CAN_Driver".center(50, '-'))

        __Driver['UDS'].UDS_can_delete()
        __Driver['UDSFun'].UDS_can_delete()

    logging.info("close CAN_Driver".center(50, '-'))
    
    try:
        if Set_up.power_Type == '2303':
            __Driver['power'].turn_off_power()
        else:
            __Driver['power'].turn_off_power()
            __Driver['power'].close()
    except Exception as e: 
        pass  
    logging.info("close power_Driver".center(50, '-'))

    __Driver['power'].close()
    logging.info("close Power".center(50, '-'))

    __Driver['jidianqi'].close()
    logging.info("close jidianqi".center(50, '-'))
    __Driver['M600'].close()
    logging.info("close M600T_Driver".center(50, '-'))


@pytest.fixture()
def action():
    blfname = datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S') + '.blf'
    logging.info("测试用例开始".center(30, '*'))
    if Set_up.testVin == []:
        uds_rep, _ = __Driver['UDS'].req_and_res_can([0x22,0xF1,0x90],3)
        if uds_rep[-17:] == [0x00] * 17:
            __Driver['CAN'].checkReqResp(__Driver,'2E F1 90' + Set_up.VINDataIdentifier_hex, '6E F1 90', 3, 1, True)
            uds_rep, _ = __Driver['UDS'].req_and_res_can([0x22,0xF1,0x90],3)
        Set_up.testVin = uds_rep[-17:]
    yield
    time.sleep(0.5)
    if Set_up.drive_type == ZCAN_USBCANFD_200U:
        __Driver['UDS'].req_and_res_can(0x10, [0x01])
    else:
        __Driver['CAN'].write_db_signal(Set_up.NetName,'VIU0', 'VIU_Route_Body3', 'IPB_VehicleSpeedValid2', 1)
        __Driver['CAN'].write_db_signal(Set_up.NetName,'VIU0', 'VIU_Route_Body3', 'IPB_VehicleSpeed2', 0)
        __Driver['UDS'].req_and_res_can([0x10,0x01],2)
    time.sleep(1)
    logging.info("测试用例结束".center(30, '*'))

# @pytest.fixture()
# def WakeUp():
#     logging.info("开始发送唤醒信号".center(30, '*'))
#     wakeup_data_str = ','.join([f'0x{byte:x}' for byte in Set_up.WakeUpData])
#     logging.info(f"唤醒ID = 0x{Set_up.WakeUpID:x}, 唤醒数据 = [{wakeup_data_str}], 唤醒周期 = {Set_up.WakeUpCycle}ms")
#     __Driver['UDS'].start_send_frame_loop(Set_up.WakeUpID, Set_up.WakeUpData, Set_up.WakeUpCycle)
#     yield
#     time.sleep(0.5)
#     __Driver['UDS'].WakeUpStatus = False
#     logging.info("结束发送唤醒信号".center(30, '*'))
    
@pytest.fixture()
def BCMPower_Gear():
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x12D', 'BCMPower_Gear_12D_S', 3)
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x3D9', 'Total_Distance_3D9s5_S', 10)
    logging.info("设置BCMPower_Gear_12D_S为ON档,并等待3s".center(30, '*'))
    time.sleep(3)
    yield
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x12D', 'BCMPower_Gear_12D_S', 1)
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x3D9', 'Total_Distance_3D9s5_S', 10)
    logging.info("设置BCMPower_Gear_12D_S为OFF档,并等待0.5s".center(30, '*'))
    time.sleep(0.8)


@pytest.fixture()
def Fault_Injection():
    logging.info("采用故障注入,清除故障".center(30, '*'))
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'profile 0',20)

    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNeverDone_Enable 0 C 1 1',20)
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNeverDone_val 0 s 1 0',20)

    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNotDone_Enable 0 C 1 1',20)
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNotDone_val 0 s 1 0',20)

    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_VariantCodeDet_Enable 0 C 1 1',20)
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_VariantCodeDet_val 0 s 1 0',20)
    time.sleep(3)
    yield
    time.sleep(0.5)

@pytest.fixture()
def power_reset():
    # __Driver['power'].Enable(False)
    # time.sleep(1)
    # __Driver['power'].Enable(True)
    time.sleep(0.1)

@pytest.fixture(scope='function',autouse=False)
def default_session():
    time.sleep(2)
    with allure.step('Step1:Request [0x10,0x01]'):
        __Driver['UDS'].req_and_res_can(0x10, [0x01])

@pytest.fixture(scope='function',autouse=False)
def extend_session():
    time.sleep(2)
    with allure.step('Step1:Request [0x10,0x03]'):
        __Driver['UDS'].req_and_res_can(0x10, [0x03])

@pytest.fixture(scope='function',autouse=False)
def programming_session():
    time.sleep(2)
    with allure.step('Step1:Request [0x10,0x03]'):
        __Driver['UDS'].req_and_res_can(0x10, [0x03])
    time.sleep(0.1)
    __Driver['CAN'].unlock(__Driver,2)
    with allure.step('Step4:Request [0x10,0x02]'):
        __Driver['UDS'].req_and_res_can(0x10, [0x02])
    time.sleep(2)
    yield
    __Driver['UDS'].req_and_res_can(0x10, [0x01])


# @pytest.fixture(scope=“class”,autouse=True)
@pytest.fixture(scope='module',autouse=True)
def power_reset_for_class(): 
    __Driver['power'].turn_off_power()
    logging.info('power reset for module')
    time.sleep(1)
    __Driver['power'].turn_on_power()
    __Driver['power'].set_voltage(12)
    logging.info('Wait 5 seconds')
    time.sleep(5)

@pytest.fixture()
def InitRSU():
    __Driver['M600'].InitRSU()
    yield
    pass
    

def pytest_configure(config):

    pss = { '01 16 09 06 00':'美信',
            '0b 17 09 0d 00':'MPC_70331',
            '03 16 0c 1f 00':'MPC_70331',
            '05 16 0c 1f 00':'MPC_4323',
            '06 16 0c 1f 00':'MPC_9840',
            '0b 17 0a 08 00':'MPC_70331_230Pro',
            '0c 18 03 05 00':'MPC_70331_220Pro_j',
            }

    PowerSupplySolution = pss[Set_up.ECUHardwareVersionNumber]
    PowerSupplySolution = Set_up.Dut_Type
    # Add interface address and project info
    #TODO, below info import from common folder Comm_Config.py file
    config._metadata["Software version"] = Set_up.Dut_Type + ' - V' + Set_up.APP_ver[0] + '.' + Set_up.APP_ver[1:3]+ '.' + Set_up.APP_ver[3:5]
    config._metadata["boot version"] = Set_up.bootver
    config._metadata["Build tag"] = "XX.XX.XX.XX"
    config._metadata["SN"] = "test 0.0.0.1"
    config._metadata["Dut type"] = PowerSupplySolution
    config._metadata["Test time"] = datetime.date.today()

    # Delete Java_Home
    config._metadata.pop("Python")
    config._metadata.pop("Plugins")
    config._metadata.pop("Packages")

    if os.path.exists('../Radar_report.html') and os.path.getsize('../Radar_report.html') > 16000:
        '''拷贝allure-results'''
        source_path = "../allure-results"
        target_path = "../" + PowerSupplySolution + datetime.datetime.now().strftime("_%y%m%d%H%M")
        allure_target_path = target_path + "/allure-results"
        if not os.path.exists(target_path):
            # 如果目标路径不存在原文件夹的话就创建
            os.makedirs(allure_target_path)
        if os.path.exists(source_path):
            # 如果目标路径存在原文件夹的话就先删除
            # shutil.rmtree(allure_target_path)
            time.sleep(1)
            shutil.move(source_path, allure_target_path)

        '''拷贝Radar_report'''
        source_path = "../Radar_report.html"
        html_target_path = target_path + "/"
        time.sleep(1)
        shutil.move(source_path, html_target_path)

@pytest.fixture()
def set_rbs():
    logging.info("停止发送EDR报文".center(30, '*'))
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x74A',False) 
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x74A',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x751',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x752',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x753',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75B',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75C',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75D',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75E',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75F',False)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x764',False)
    time.sleep(0.1)
    yield
    logging.info("开始发送EDR报文".center(30, '*'))
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x74A',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x751',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x752',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x753',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75B',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75C',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75D',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75E',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x75F',True)
    __Driver['CAN2'].Enable_rbs_message(Set_up.NetName,'EDR','EDR_0x764',True)


@pytest.mark.optionalhook
def pytest_html_results_summary(prefix, summary, postfix):
    prefix.extend([html.p("Tester: YangLiang")])
    prefix.extend([html.p("Report version: 0.0.1")])


@pytest.mark.optionalhook
def pytest_html_results_table_header(cells):
    cells.pop()

@pytest.mark.optionalhook
def pytest_html_results_table_row(report, cells):
    cells.pop()

@pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()
	
@pytest.fixture(scope="function", autouse=True)
def mod_header(request):
    item_name = request.node.nodeid.split("::")[-1]
    logging.info('\n-----------------')
    logging.info('Item name : %s' % item_name)
    
    if Set_up.drive_type == ZCAN_USBCANFD_200U:
        blfname = datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S') + '.asc'
        __Driver['CAN'].start_logging(os.path.join(Set_up.root, f"blflog\{item_name}_{blfname}"))
    else:
        blfname = datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S') + '.blf'
        log_path = os.path.join(Set_up.root, f"blflog\{item_name}_{blfname}")
        __Driver['CAN'].tsapp_start_logging(log_path)
    yield
    if Set_up.drive_type == ZCAN_USBCANFD_200U:
        __Driver['CAN'].stop_logging()
    else:
        __Driver['CAN'].tsapp_stop_logging()
    
    # # 根据测试结果决定是否删除日志文件
    # if request.node.rep_call.failed:
    #     logging.info("测试失败，日志文件保留: %s", log_path)
    # else:
    #     time.sleep(0.01)
    #     os.remove(log_path)
    #     # logging.info("测试成功，日志文件已删除: %s", log_path)

